/*
* This file provided by Facebook is for non-commercial testing and evaluation
* purposes only. Facebook reserves all rights not expressly granted.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.facebook.fresco.samples.showcase.imagepipeline;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.IdRes;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.Toast;
import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.drawee.interfaces.DraweeController;
import com.facebook.drawee.view.SimpleDraweeView;
import com.facebook.fresco.samples.showcase.BaseShowcaseFragment;
import com.facebook.fresco.samples.showcase.R;
import com.facebook.fresco.samples.showcase.imagepipeline.widget.ResizableFrameLayout;
import com.facebook.imagepipeline.common.ResizeOptions;
import com.facebook.imagepipeline.request.ImageRequest;
import com.facebook.imagepipeline.request.ImageRequest.CacheChoice;
import com.facebook.imagepipeline.request.ImageRequestBuilder;
import com.facebook.imagepipeline.request.MediaVariations;
public class MediaVariationsFragment extends BaseShowcaseFragment {
private static final String TAG = "MediaVariationsFragment";
private static final String URI_TEMPLATE
= "http://frescolib.org/static/sample-images/monkey-selfie-%s.%s";
private static final String MEDIA_ID = "monkey-selfie";
private SimpleDraweeView mMainImageDraweeView;
private enum Size {
XS(R.id.thumb_xs, "xs", "png", 377, 523, CacheChoice.SMALL),
S(R.id.thumb_s, "s", "webp", 629, 871, CacheChoice.SMALL),
M(R.id.thumb_m, "m", "jpg", 1048, 1451, CacheChoice.DEFAULT),
L(R.id.thumb_l, "l", "jpg", 1747, 2418, CacheChoice.DEFAULT),
XL(R.id.thumb_xl, "xl", "jpg", 2912, 4030, CacheChoice.DEFAULT);
final @IdRes int thumbViewId;
final String name;
final Uri uri;
final int width;
final int height;
final CacheChoice cacheChoice;
Size(
@IdRes int thumbViewId,
String name,
String extension,
int width,
int height,
CacheChoice cacheChoice) {
this.thumbViewId = thumbViewId;
this.name = name;
this.uri = Uri.parse(String.format(URI_TEMPLATE, name, extension));
this.width = width;
this.height = height;
this.cacheChoice = cacheChoice;
}
}
private enum Mode {
MEDIA_ID_IN_REQUEST(
R.id.media_variations_mode_media_id,
R.string.imagepipeline_media_variations_toast_mode_media_id),
LISTED_IN_REQUEST(
R.id.media_variations_mode_listed_variants,
R.string.imagepipeline_media_variations_toast_mode_listed_variants),
RELY_ON_MEDIA_ID_EXTRACTOR(
R.id.media_variations_mode_media_id_extractor,
R.string.imagepipeline_media_variations_toast_mode_media_id_extractor);
final @IdRes int menuItemId;
final @StringRes int toastMessageId;
Mode(int menuItemId, int toastMessageId) {
this.menuItemId = menuItemId;
this.toastMessageId = toastMessageId;
}
}
private Mode mMode;
public MediaVariationsFragment() {
setHasOptionsMenu(true);
}
@Nullable
@Override
public View onCreateView(
LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_imagepipeline_media_variations, container, false);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
populateImagesAfterInitialLayout(view);
setMode(Mode.MEDIA_ID_IN_REQUEST);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.fragment_imagepipeline_media_variations, menu);
menu.findItem(mMode.menuItemId).setChecked(true);
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.media_variations_clear_cache) {
Fresco.getImagePipeline().clearCaches();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
getActivity().recreate();
} else {
Toast.makeText(
getActivity(),
R.string.imagepipeline_media_variations_restart_toast,
Toast.LENGTH_SHORT).show();
getActivity().finish();
}
return true;
} else if (item.getGroupId() == R.id.media_variations_modes) {
for (Mode mode : Mode.values()) {
if (mode.menuItemId == item.getItemId()) {
setMode(mode);
break;
}
}
clearMainImageAndBitmapCache();
item.setChecked(true);
}
return super.onOptionsItemSelected(item);
}
private void setMode(Mode mode) {
mMode = mode;
Toast.makeText(getActivity(), mMode.toastMessageId, Toast.LENGTH_SHORT).show();
}
@Override
public int getTitleId() {
return R.string.imagepipeline_media_variations_title;
}
private void populateImagesAfterInitialLayout(final View rootView) {
rootView.getViewTreeObserver()
.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
populateMainImage(rootView);
for (Size size : Size.values()) {
populateThumb(rootView, size.thumbViewId, size);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
rootView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
} else {
rootView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
}
});
}
private void populateThumb(View rootView, @IdRes int viewId, final Size size) {
final SimpleDraweeView draweeView = (SimpleDraweeView) rootView.findViewById(viewId);
loadThumb(draweeView, size, ImageRequest.RequestLevel.DISK_CACHE);
draweeView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
loadThumb(draweeView, size, ImageRequest.RequestLevel.FULL_FETCH);
}
});
}
private void loadThumb(
SimpleDraweeView draweeView,
Size size,
ImageRequest.RequestLevel requestLevel) {
ImageRequest request = ImageRequestBuilder.newBuilderWithSource(size.uri)
.setMediaVariations(MediaVariations.newBuilderForMediaId(MEDIA_ID)
.setForceRequestForSpecifiedUri(true)
.build())
.setLowestPermittedRequestLevel(requestLevel)
.setResizeOptions(new ResizeOptions(draweeView.getWidth(), draweeView.getHeight()))
.setCacheChoice(size.cacheChoice)
.build();
DraweeController controller = Fresco.newDraweeControllerBuilder()
.setImageRequest(request)
.setOldController(draweeView.getController())
.build();
draweeView.setController(controller);
}
private void populateMainImage(View rootView) {
mMainImageDraweeView = (SimpleDraweeView) rootView.findViewById(R.id.img_main);
loadMainImage();
mMainImageDraweeView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
loadMainImage();
}
});
ResizableFrameLayout mainImageFrameLayout =
(ResizableFrameLayout) rootView.findViewById(R.id.frame_main);
mainImageFrameLayout.init(rootView.findViewById(R.id.btn_resize));
}
private void loadMainImage() {
// Request a non-existent image to force fallback to the variations
Uri uri = Uri.parse(String.format(URI_TEMPLATE, "full", "jpg"));
ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
.setMediaVariations(getMediaVariationsForMode(mMode))
.setResizeOptions(new ResizeOptions(
mMainImageDraweeView.getWidth(),
mMainImageDraweeView.getHeight()))
.build();
Log.i(
TAG,
request.getMediaVariations() == null ? "null" : request.getMediaVariations().toString());
setDraweeControllerForRequest(request);
}
private void clearMainImageAndBitmapCache() {
Uri uri = Uri.parse(String.format(URI_TEMPLATE, "full"));
setDraweeControllerForRequest(ImageRequest.fromUri(uri));
Fresco.getImagePipeline().clearMemoryCaches();
}
private void setDraweeControllerForRequest(ImageRequest imageRequest) {
DraweeController controller = Fresco.newDraweeControllerBuilder()
.setImageRequest(imageRequest)
.setOldController(mMainImageDraweeView.getController())
.setRetainImageOnFailure(true)
.build();
mMainImageDraweeView.setController(controller);
}
@Nullable
private static MediaVariations getMediaVariationsForMode(Mode mode) {
switch (mode) {
case LISTED_IN_REQUEST:
MediaVariations.Builder builder = MediaVariations.newBuilderForMediaId(null);
for (Size size : Size.values()) {
builder.addVariant(size.uri, size.width, size.height);
}
return builder.build();
case MEDIA_ID_IN_REQUEST:
return MediaVariations.forMediaId(MEDIA_ID);
case RELY_ON_MEDIA_ID_EXTRACTOR:
// Dependent on ShowcaseMediaIdExtractor being set as part of the config
// This is done in ShowcaseApplication
return null;
}
throw new IllegalStateException("Invalid media variations mode set");
}
}